#ifndef __CALLBACK_CONNECTION_HPP
#define __CALLBACK_CONNECTION_HPP

#include "feature.hpp"
#include <tuple>
namespace callback {

namespace internal {

template <typename TService> class ConnectionBase {
public:
  virtual void DoCall(typename TService::TupleOfArgs tuple_of_args) = 0;
  auto Append(ConnectionBase &node) {
    if (this == &node) {
      return;
    }
    auto itr = this;
    while (itr->m_next != nullptr) {
      itr = itr->m_next;
      if (itr == &node) {
        return;
      }
    }
    itr->m_next = &node;
  }

protected:
  ConnectionBase *m_next{nullptr};
};

template <typename TService, auto... fn>
class Connection : public ConnectionBase<TService> {
public:
  static constexpr auto Call(auto... args) {
    (Feature<TService, fn>::Call(args...), ...);
  }

protected:
  auto
  DoCall(typename TService::TupleOfArgs tuple_of_args) -> void override final {
    std::apply([](auto... args) { Call(args...); }, tuple_of_args);
    if (this->m_next != nullptr) {
      this->m_next->DoCall(tuple_of_args);
    }
  }
};

} // namespace internal

} // namespace callback

#endif // !__CALLBACK_CONNECTION_HPP